//泛型 Generic 用于入参的时候自己判断是什么类型
// T为定义一个泛型,入参也是泛型,返回也是泛型 --具体什么类型为传参的时候传的什么类型就是什么类型
function identify<T>(arg: T): T{
  return arg
}
// 交给TS推判类型
console.log('identify', identify('字符串'));//identify 字符串
// 或指定类型
console.log('identify或指定类型==>', identify<string>('哈哈'));//哈哈

// ---------------------接口中使用泛型------------------------------------
/**
 * <T>定义泛型
 * (arg:T) 参数泛型
 * T 返回泛型
 */
interface GenericIdntify{
  <T>(arg:T):T
}
function identify2<T>(arg: T): T{
  return arg
}
// GenericIdntify赋值给到identify2
let myIdentify: GenericIdntify = identify2
console.log('接口中使用泛型', myIdentify<string>('my-string'));//my-string
console.log('接口中使用泛型不指定类型', myIdentify(22));//22


// ------------------------------------在接口上定义泛型------------------------------------
console.log('--------------------------------在接口上定义泛型--------------------',);

interface GenericIdntify2<T>{
  (arg:T):T
}
function identify3<T>(arg: T): T{
  return arg
}
// GenericIdntify定义类型并赋值给到identify2
let myIdentify2: GenericIdntify2<number|string> = identify3
console.log('GenericIdntify定义number类型并赋值给到identify2',myIdentify2(30));//30
console.log('GenericIdntify定义string类型并赋值给到identify2', myIdentify2('指定string类型'));//指定string类型

console.log('--------------------------------为泛型添加约束--------------------',);
/**
 * @param <T extends { length: any }> 约束obj中一定要有一个length属性并随意类型
 * @param obj 任意类型
 */
function getLength<T extends { length: any }>(obj: T): any{
  return obj.length
}
const obj = {
  name: '约束类型',
  length:10
}
console.log('为泛型添加约束getLength', getLength(obj));//10


/**
 * 
 * @param  <T extends number> 约束传入的是数字类型
 * @returns 返回约束的类型
 */
function getLength2<T extends number>(obj: T): any{
  return obj
}
const obj2 = 25
console.log('为泛型添加约束数字类型', getLength2(obj2));//25

console.log('--------------------------------泛型----class--------------------',);
class CountNumber<T>{
  number1: T;
  number2: T;
  constructor(num1: T, num2: T) {
    this.number1 = num1
    this.number2=num2
  }
  calcalete(): number{//返回number类型
    return +this.number1* +this.number2
    
  }
}
// const countNumber = new CountNumber<number>(10, 20)//200
const countNumber = new CountNumber<string>('10', '20')//200
console.log('countNumber', countNumber.calcalete());
console.log('--------------------------------泛型--定义类型为number----class--------------------',);
class CountNumber2<T extends number>{
  number1: T;
  number2: T;
  constructor(num1: T, num2: T) {
    this.number1 = num1
    this.number2=num2
  }
  calcalete(): number{//返回number类型
    return +this.number1 / +this.number2
    
  }
}
const countNumber2 = new CountNumber2(10, 20)
console.log('countNumber2',countNumber2.calcalete());//0.5